package codeCreate.restfulAPICreate.strategyService.impl;

import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import codeCreate.domain.DeviceCriteria;
import codeCreate.restfulAPICreate.strategyService.StrategyService;
import codeCreate.restfulAPICreate.util.BaseConfiguration;
import codeCreate.restfulAPICreate.util.annotation.type.Column;

public class BeanToJsonStringStrategy extends BaseConfiguration implements StrategyService<String> {
    private Class<?> beanClass;
    private String filePath = "C:\\Users\\Administrator\\Desktop\\";
    private String fileName = "beanJson.txt";
    private String StationSymbol = "\"xxx\"";
    private Class<?>[] numberReturnType = { Integer.class, Long.class, Float.class, Double.class, Short.class };
    private Class<?>[] notNumberBaseReturnType = { char.class, Date.class, String.class };
    private Class<?>[] listReturnType = { ArrayList.class, LinkedList.class };
    private Class<?>[] mapReturnType = { HashMap.class };

    public BeanToJsonStringStrategy(Class<?> beanClass) {
        this.beanClass = beanClass;
    }

    @Override
    public String create() throws Exception {
        File file = new File(filePath + fileName);
        FileWriter fileWriter = new FileWriter(file);
        String resultJson = recursionResolve(beanClass, 1);
        fileWriter.write(resultJson);
        fileWriter.close();
        return resultJson;
    }

    private String recursionResolve(Class<?> beanClass, int tier) {
        StringBuffer sBuffer = new StringBuffer(BRACE_PREFIX_);
        Field[] fields = beanClass.getDeclaredFields();
        int columnLength = 0;
        for (Field field : fields) {
            Column column = field.getAnnotation(Column.class);
            if (null == column) {
                continue;
            }
            columnLength++;
        }
        int flag = 1;
        for (Field field : fields) {
            Column column = field.getAnnotation(Column.class);
            if (null == column) {
                continue;
            }
            sBuffer.append(getTabSymbol(tier)).append(QUOTE).append(field.getName()).append(QUOTE).append(BLANK)
                    .append(COLON).append(BLANK);
            Class<?> returnType = field.getType();
            if (Arrays.asList(numberReturnType).contains(returnType)) {
                sBuffer.append("200");
                if (flag < columnLength) {
                    sBuffer.append(COMMA).append(NL);
                } else {
                    sBuffer.append(NL);
                }
            } else if (returnType.isPrimitive() || Arrays.asList(notNumberBaseReturnType).contains(returnType)) {
                sBuffer.append(QUOTE).append("xxx").append(QUOTE);
                if (flag < columnLength) {
                    sBuffer.append(COMMA).append(NL);
                } else {
                    sBuffer.append(NL);
                }
            } else if (returnType.isAssignableFrom(List.class)) {
                sBuffer.append(BRACKET_PREFIX);
                Class genaricClass = null;
                Type type = field.getGenericType();
                if (type instanceof ParameterizedType) {
                    ParameterizedType t = (ParameterizedType) (field.getGenericType());
                    genaricClass = (Class) t.getActualTypeArguments()[0];
                }
                if (Arrays.asList(numberReturnType).contains(returnType)) {
                    sBuffer.append(createPrimaryNumberList(3));
                }
                if (genaricClass.isPrimitive() || Arrays.asList(notNumberBaseReturnType).contains(genaricClass)) {
                    sBuffer.append(createPrimaryStringList(3));
                } else {
                    sBuffer.append(recursionResolve(genaricClass, tier + 1));
                    if (genaricClass.getDeclaredFields().length < 6) {
                        sBuffer.append(COMMA).append(NL).append(getTabSymbol(tier))
                                .append(recursionResolve(genaricClass, tier + 1));
                    }
                }
                sBuffer.append(BRACKET_SUFFIX);
                if (flag < columnLength) {
                    sBuffer.append(COMMA).append(NL);
                } else {
                    sBuffer.append(NL);
                }
            } else {
                sBuffer.append(recursionResolve(returnType, tier + 1));
            }
            flag++;
        }
        sBuffer.append(getTabSymbol(tier - 1)).append(BRACE_SUFFIX_);
        return sBuffer.toString();
    }

    private String getTabSymbol(int tier) {
        StringBuffer sBuffer = new StringBuffer();
        while (tier > 0) {
            sBuffer.append(TAB);
            tier--;
        }
        return sBuffer.toString();
    }

    private String createPrimaryStringList(int number) {
        StringBuffer sBuffer = new StringBuffer();
        while (number > 0) {
            if (number > 1) {
                sBuffer.append(BLANK).append(StationSymbol).append(BLANK).append(COMMA);
            } else {
                sBuffer.append(BLANK).append(StationSymbol).append(BLANK);
            }
            number--;
        }
        return sBuffer.toString();
    }

    private Object createPrimaryNumberList(int number) {
        StringBuffer sBuffer = new StringBuffer();
        Random random = new Random();
        while (number > 0) {
            if (number > 1) {
                sBuffer.append(BLANK).append(random.nextInt(50) + 1).append(BLANK).append(COMMA);
            } else {
                sBuffer.append(BLANK).append(StationSymbol).append(BLANK);
            }
            number--;
        }
        return sBuffer.toString();
    }

    public void setBeanClass(Class<?> beanClass) {
        this.beanClass = beanClass;
    }

    public static void main(String[] args) {
        BeanToJsonStringStrategy beanToJsonString = new BeanToJsonStringStrategy(DeviceCriteria.class);
        try {
            System.out.println(beanToJsonString.create());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
